package mspbots.data.tl.script.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import mspbots.data.tl.base.AbstractBaseServiceImpl;
import mspbots.data.tl.script.entity.ScriptAction;
import mspbots.data.tl.script.entity.SysDataset;
import mspbots.data.tl.script.mapper.SysDatasetMapper;
import mspbots.data.tl.script.service.ScriptService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;

import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * @author Jay.Yang
 */

@Service
@Log4j2
@RequiredArgsConstructor
@DS("master")
public class ScriptServiceImpl extends AbstractBaseServiceImpl<SysDatasetMapper, SysDataset>
        implements ScriptService {

    private final SysDatasetMapper sysDatasetMapper;
    private final ScriptAction scriptAction;
    private final ScriptEngine scriptEngine;
    @Value("${mspbots.source.ip}")
    private String sourceIp = "192.168.0.2";

    @Override
    public Object sync(Long datasetId) {
        Bindings bindings = scriptEngine.createBindings();
        bindings.put("api", scriptAction);
        Object result = null;
        SysDataset sysDataset = sysDatasetMapper.selectById(datasetId);
        if (ObjectUtils.isEmpty(sysDataset)) {
            log.warn("SysDataset id:{}, It doesn't exist!", datasetId);
            return result;
        }
        if (StringUtils.isEmpty(sysDataset.getRefreshContent())){
            log.warn("SysDataset id:{}, refreshContent is Empty!", datasetId);
            return result;
        }
        if (SysDataset.REFRESH_TYPE_GROOVY.equals(sysDataset.getRefreshType())) {
            try {
                result = scriptEngine.eval(sysDataset.getRefreshContent(), bindings);
                log.info("SysDataset id:{}, groovy eval success!", datasetId);
            } catch (ScriptException e) {
                log.error("SysDataset id:{}, groovy eval failed!", datasetId);
                log.error(e.getMessage());
                result = false;
            }
        } else if (SysDataset.REFRESH_TYPE_SQL.equals(sysDataset.getRefreshType())) {
            super.databaseClient.execute(sysDataset.getRefreshContent()).fetch().all().subscribe();
        } else if (SysDataset.REFRESH_TYPE_VIEW.equals(sysDataset.getRefreshType())
                || SysDataset.REFRESH_TYPE_MATERIALIZEDVIEW.equals(sysDataset.getRefreshType())) {
            super.databaseClient.execute(sysDataset.getRefreshContent()
                    .replace("{source_ip}", sourceIp)).fetch().all().subscribe();
        } else {
            log.warn("SysDataset id:{}, refreshType:{},non-supported!", datasetId, sysDataset.getRefreshType());
        }
        sysDataset.setRefreshTime(LocalDateTime.now());
        sysDatasetMapper.updateById(sysDataset);
        return result;
    }

    @Override
    public Flux<Map<String, Object>> executeSqlData(Map<String, String> map) {
        if (map.containsKey(SysDataset.REFRESH_TYPE_SQL)) {
            return super.databaseClient.execute(map.get(SysDataset.REFRESH_TYPE_SQL))
                    .fetch().all();
        } else if (map.containsKey(SysDataset.REFRESH_TYPE_VIEW)) {
            return super.databaseClient.execute(map.get(SysDataset.REFRESH_TYPE_VIEW)
                    .replace("{source_ip}", sourceIp)).fetch().all();
        } else if (map.containsKey(SysDataset.REFRESH_TYPE_MATERIALIZEDVIEW)) {
            return super.databaseClient.execute(map.get(SysDataset.REFRESH_TYPE_MATERIALIZEDVIEW)
                    .replace("{source_ip}", sourceIp)).fetch().all();
        }
        return Flux.empty();
    }

}
